﻿using Apewer.Network;
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;

namespace Apewer.Web
{

    /// <summary>API 调用器。</summary>
    public sealed class ApiInvoker
    {

        #region

        private static ApiInvoker _default = new ApiInvoker();

        /// <summary>默认调用器实例。</summary>
        public static ApiInvoker Default { get => _default; }

        #endregion

        object _locker = new object();
        bool _initialized = false;

        /// <summary>获取或设置要使用的 API 入口。</summary>
        public ApiEntries Entries { get; set; }

        /// <summary>获取或设置 Logger。</summary>
        public Logger Logger { get; set; }

        /// <summary>获取或设置选项。</summary>
        public ApiOptions Options { get; set; }

        /// <summary>异常捕获程序。</summary>
        public Action<ApiCatch> Catcher { get; set; }

        /// <summary>输出前的检查。</summary>
        public ApiPreOutput PreOutput { get; set; }

        /// <summary>执行初始化程序，每个 ApiInvoker 实例仅执行一次初始化。</summary>
        public void Initialize(Action action)
        {
            if (action == null) return;
            lock (_locker)
            {
                if (_initialized) return;
                action.Invoke();
                _initialized = true;
            }
        }

        /// <summary>发起调用。</summary>
        /// <exception cref="ArgumentNullException" />
        public void Invoke(ApiProvider provider)
        {
            if (provider == null) throw new ArgumentNullException(nameof(provider));

            var entries = Entries;
            if (entries == null) entries = ApiEntries.AppDomain();
            Entries = entries;
            Invoke(provider, entries);
        }

        /// <summary>发起调用。</summary>
        /// <exception cref="ArgumentNullException" />
        public void Invoke(ApiProvider provider, ApiEntries entries)
        {
            if (provider == null) throw new ArgumentNullException(nameof(provider));
            if (entries == null) throw new ArgumentNullException(nameof(entries));

            var context = new ApiContext(this, provider, entries);
            var processor = new ApiProcessor(context);
            processor.Run();
        }

    }

}
